import ctypes
import os.path as osp
from enum import Enum
import numpy as np
from enum import Enum


class WLWWModeOptType(Enum):
    CardiacFluCine = 1
    RoadMap = 2
    NeurologyFluCine = 3
    NeurologyDSA = 4
    Other = 5,


class AutoWLWW(object):
    def __init__(self, logger_name="autoWLWW"):
        self.dll_handle = ctypes.windll.LoadLibrary(osp.join(osp.dirname(__file__), "dll", "autoWLWW.dll"))
        self.logger_name = logger_name.encode('utf-8')

        self.dll_handle.autoWLWWCreateHandle.restype = ctypes.POINTER(ctypes.c_void_p)
        self.dll_handle.autoWLWWCreateHandle.argtypes = [ctypes.c_char_p]
        self.autoHandle = self.dll_handle.autoWLWWCreateHandle(self.logger_name)

        self.dll_handle.autoWLWWInitialization.restype = ctypes.c_int
        self.dll_handle.autoWLWWInitialization.argtypes = [ctypes.c_void_p, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_bool]

        self.dll_handle.autoWLWWResetLoggerName.restype = ctypes.c_int
        self.dll_handle.autoWLWWResetLoggerName.argtypes = [ctypes.c_void_p, ctypes.c_char_p]

        self.dll_handle.autoWLWWProcess.restype = ctypes.c_int
        self.dll_handle.autoWLWWProcess.argtypes = [
            ctypes.c_void_p,
            np.ctypeslib.ndpointer(np.uint16),
            np.ctypeslib.ndpointer(np.uint16),
            ctypes.c_uint16
        ]

        self.dll_handle.autoWLWWResetProcess.restype = ctypes.c_int
        self.dll_handle.autoWLWWResetProcess.argtypes = [ctypes.c_void_p]

        self.dll_handle.autoWLWWDestroy.restype = ctypes.c_int
        self.dll_handle.autoWLWWDestroy.argtypes = [ctypes.c_void_p]

    def Initialization(self, height, width, use_configile=True):
        self.dll_handle.autoWLWWInitialization(self.autoHandle, height, width, use_configile)

    def ResetLoggerName(self, logger_name):
        logger_name = logger_name.encode('utf-8')
        self.dll_handle.autoWLWWResetLoggerName(self.autoHandle, logger_name)

    def Process(self, img: np.ndarray, mode_opt):
        if img.dtype != np.uint16:
            raise TypeError('img must be uint16')
        result_img = np.zeros_like(img)
        err = self.dll_handle.autoWLWWProcess(self.autoHandle, img, result_img, mode_opt)
        if err != 0:
            raise RuntimeError(err)
        return result_img

    def ResetProcess(self):
        self.dll_handle.autoWLWWResetProcess(self.autoHandle)

    def __del__(self):
        self.dll_handle.autoWLWWDestroy(self.autoHandle)

